#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
基于物品的协同过滤推荐算法
'''
import numpy as np


def cal_two_good_sim(good1Stars: list, good2Stars: list):
    """
    欧式距离计算两个商品之间的相似度
    :param good1Stars:
    :param good2Stars:
    :return:
    """
    return np.sqrt(((np.array(good1Stars) - np.array(good2Stars)) ** 2).sum())


class TF:
    def __init__(self, us, gd, allList):
        self.users = us
        self.goods = gd
        self.allUserGoodsStarList = allList

    def converRow2Col(self):
        """
        行转列
        :return:
        """
        return np.array(self.allUserGoodsStarList).transpose().tolist()

    def cal_all_good_sim(self):
        """
        计算所有商品之间的相似度
        :return:
        """
        resDic = {}
        tempList = self.converRow2Col()
        for i in range(0, len(tempList)):
            for j in range(i + 1, len(tempList)):
                resDic[str(i) + '-' + str(j)] = cal_two_good_sim(tempList[i], tempList[j])
        return resDic

    def calrecommendGood(self, username: str) -> list:

        """
        计算待推荐的商品
        :return:list
        """
        temp = {}
        goods_sim_dic = self.cal_all_good_sim()
        userindex = self.users.index(username)
        target_user_goods_list = self.allUserGoodsStarList[userindex]
        for i in range(0, len(target_user_goods_list)):
            for j in range(i + 1, len(target_user_goods_list)):
                if target_user_goods_list[i] == 1 and target_user_goods_list[j] == 0 and \
                        (goods_sim_dic.get(str(i) + '-' + str(j)) is not None or \
                         goods_sim_dic.get(str(j) + '-' + str(i)) is not None):
                    sim = goods_sim_dic.get(str(i) + '-' + str(j)) if (
                            goods_sim_dic.get(str(i) + '-' + str(j)) is not None) else goods_sim_dic.get(
                        str(j) + '-' + str(i))
                    temp[j] = sim
                elif target_user_goods_list[i] == 0 and target_user_goods_list[j] == 1 and \
                        (goods_sim_dic.get(str(i) + '-' + str(j)) is not None or \
                         goods_sim_dic.get(str(j) + '-' + str(i)) is not None):
                    sim = goods_sim_dic.get(str(i) + '-' + str(j)) if (
                            goods_sim_dic.get(str(i) + '-' + str(j)) is not None) else goods_sim_dic.get(
                        str(j) + '-' + str(i))
                    temp[i] = sim
        temp = sorted(temp.items(), key=lambda d: d[1], reverse=True)
        print("相似度排序：", temp)
        recommendlist = [self.goods[i] for i, v in temp]

        print("待推荐列表：", recommendlist)
        return recommendlist


if __name__ == '__main__':
    users = ["小明", "小花", "小美", "小张", "小李"]
    goods = ["物品1", "物品2", "物品3", "物品4", "物品5", "物品6", "物品7"]
    allUserGoodsStarList = [
        [1, 1, 1, 0, 1, 0, 0],
        [0, 1, 1, 0, 0, 1, 0],
        [1, 0, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 0, 0],
        [1, 1, 0, 1, 0, 1, 1]]
    # TF(users, goods, allUserGoodsStarList).cal_all_good_sim()
    # TF(users, goods, allUserGoodsStarList).calrecommendGood("小李")
    TF(users, goods, allUserGoodsStarList).calrecommendGood("小花")
